﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using M3G;

namespace MyTestProject {

    public class TestGroup {
        [Fact]
        public void TestConstructor () {
            var grp = new Group ();

            Assert.Equal (0, grp.ChildCount);
            Assert.Equal (false, grp.LODEnabled);
            Assert.Equal (0.0f, grp.LODOffset);
            Assert.Equal (0.0f, grp.LODHysteresis);
            Assert.Equal (-1, grp.LODChild);
            Assert.Equal (0.0f, grp.LODBlendFactor);
        }

        [Fact]
        public void TestParent () {
            var grp1 = new Group ();
            var grp2 = new Group ();
            grp1 += grp2;

            Assert.Equal (grp1, grp2.Parent);
        }

        [Fact]
        public void TestAddChild () {
            var grp1 = new Group ();
            var grp2 = new Group ();
            var grp3 = new Group ();
            grp1 += grp2;
            grp1 += grp3;

            Assert.Equal (2, grp1.ChildCount);
            Assert.Equal (grp3, grp1.Child[0]);
            Assert.Equal (grp2, grp1.Child[1]);
        }

        [Fact]
        public void TestInsertChild () {
            var grp1 = new Group ();
            var grp2 = new Group ();
            var grp3 = new Group ();
            var grp4 = new Group ();
            grp1.InsertChild (grp2, 0);
            grp1.InsertChild (grp3, 0);
            grp1.InsertChild (grp4, 1);

            Assert.Equal (3, grp1.ChildCount);
            Assert.Equal (grp3, grp1.Child[0]);
            Assert.Equal (grp4, grp1.Child[1]);
            Assert.Equal (grp2, grp1.Child[2]);
        }

        [Fact]
        public void TestRemoveChild () {
            var grp1 = new Group ();
            var grp2 = new Group ();
            var grp3 = new Group ();
            grp1.AddChild (grp2);
            grp1.AddChild (grp3);
            grp1.RemoveChild (grp2);

            Assert.Equal (1, grp1.ChildCount);
            Assert.Equal (grp3, grp1.Child[0]);
        }


        [Fact]
        public void TestSetLODEnabledHysteresis () {
            var grp1 = new Group ();
            grp1.SetLODEnable (true, 0.5f);

            Assert.Equal (true, grp1.LODEnabled);
            Assert.Equal (0.5f, grp1.LODHysteresis);

        }


        [Fact]
        public void TestSetLODOffset () {
            var grp = new Group ();
            grp.LODOffset = 5.0f;

            Assert.Equal (5.0f, grp.LODOffset);
        }


        /**
         * Find()がシーングラフ全体を探索することを確認するテスト
         * */
        [Fact]
        public void TestFind () {
            var grp1 = new Group ();
            var grp2 = new Group ();
            var grp3 = new Group ();
            grp1.UserID = 1;
            grp2.UserID = 2;
            grp3.UserID = 3;

            grp1 += grp2;
            grp2 += grp3;

            Assert.Equal (grp1, grp1.Find (1));
            Assert.Equal (grp2, grp1.Find (2));
            Assert.Equal (grp3, grp1.Find (3));
        }

        /**
         * FindAll<T>()がシーングラフ全体を探索することを確認するテスト
         * */
        [Fact]
        public void TestFindAll () {
            var grp1 = new Group ();
            var grp2 = new Group ();
            var lgh  = new Light ();
            grp1 += grp2;
            grp2 += lgh;

            var query1 = grp1.FindAll<Group> ();
            var query2 = grp1.FindAll<Light> ();

            Assert.Equal (2, query1.Length);
            Assert.Equal (grp1, query1[0]);
            Assert.Equal (grp2, query1[1]);

            Assert.Equal (1, query2.Length);
            Assert.Equal (lgh, query2[0]);
        }

        [Fact]
        public void TestReferences () {
            var grp1 = new Group ();
            var grp2 = new Group ();
            var grp3 = new Group ();
            grp1.UserID = 1;
            grp2.UserID = 2;
            grp3.UserID = 3;

            grp1 += grp2;
            grp2 += grp3;

            var refs = grp1.References;
  
            Assert.Equal (2,    refs.Length);
            Assert.Equal (grp2, refs[0]);
            Assert.Equal (grp3, refs[1]);
        }

        [Fact]
        public void TestGetReferences () {
            var grp1 = new Group ();
            var grp2 = new Group ();
            var grp3 = new Group ();
            grp1 += grp2;
            grp1 += grp3;

            var refs      = new Group[2];
  
            Assert.Equal (2, grp1.GetReferences (null));
            Assert.Equal (2, grp1.GetReferences (refs));
            Assert.Same (grp3, refs[0]);
            Assert.Same (grp2, refs[1]);
        }

        [Fact]
        public void TestDuplicate () {
            var grp1 = new Group ();
            var grp2 = new Group ();
            var grp3 = new Group ();
            grp1.AddChild (grp2);
            grp2.AddChild (grp3);
            grp1.SetLODEnable (true, 0.5f);
            grp1.LODOffset = 5.0f;
            grp1.UserID = 100;

            var grp = new Group ();
            grp.AddChild (grp1);

            var dup = (Group)grp1.Duplicate ();

            Assert.Equal (null, dup.Parent);
            Assert.Equal (grp1.ChildCount, dup.ChildCount);
            Assert.Equal (grp1.LODEnabled, dup.LODEnabled);
            Assert.Equal (grp1.LODOffset, dup.LODOffset);
            Assert.Equal (grp1.LODHysteresis, dup.LODHysteresis);
            Assert.Equal (grp1.LODChild, dup.LODChild);
            Assert.Equal (grp1.LODBlendFactor, dup.LODBlendFactor);
            Assert.Equal (grp1.UserID, dup.UserID);
        }

    }
}
